Skip to content

Conversation

@almighty55555
Copy link
Collaborator

#️⃣연관된 이슈

ex) #이슈번호, #이슈번호
Closes #60

📝 PR 유형

해당하는 유형에 'x'로 체크해주세요.

  • 기능 추가 (Feature)
  • 버그 수정 (Bug Fix)
  • 코드 개선 (Refactoring)
  • 스타일 변경 (UI/UX)
  • 문서 작업 (Documentation)
  • 환경 설정 (Configuration)
  • 기타 (Other)

📝작업 내용

  • 가게 정보 편집 페이지 구현
  • API 연동 및 테스트

이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능)

스크린샷 (선택)

💬리뷰 요구사항(선택)

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요?

@almighty55555 almighty55555 added the Feature (기능 추가) 기능을 추가합니다. label May 3, 2025
@github-actions github-actions bot requested review from cozy-ito and jeonghwanJay May 3, 2025 14:55
@netlify
Copy link

netlify bot commented May 3, 2025

Deploy Preview for thejulge1 ready!

Name Link
🔨 Latest commit 576f8a2
🔍 Latest deploy log https://app.netlify.com/sites/thejulge1/deploys/68164669aafaee00086d94c7
😎 Deploy Preview https://deploy-preview-72--thejulge1.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Collaborator

@cozy-ito cozy-ito left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다! 👍

import { useUserStore } from "@/hooks/useUserStore";
import { extractDigits, numberCommaFormatter } from "@/utils/number";

const CATEGORY_OPTIONS = [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. ShopRegisterPage에도 동일한 상수가 있던데, constants 폴더로 분리해서 재사용 하면 어떨까요? 🤔
  2. labelvalue 값이 같다면, 아래처럼 작성해도 좋을 것 같아요!
const CATEGORY_OPTIONS = ["한식", "중식", "일식", ... ].map((category) => ({ label: category, value: category }));

{ label: " ... ", value: " ... " }를 반복 작성하지 않아도 되니까요! 😄

Comment on lines 71 to 80
const shop = res.data.item;
setForm({
name: shop.name,
category: shop.category,
address1: shop.address1,
address2: shop.address2,
originalHourlyPay: numberCommaFormatter(shop.originalHourlyPay),
description: shop.description,
});
if (shop.imageUrl) setImagePreview(shop.imageUrl);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구조분해할당, 단축 속성을 활용하면 더 코드가 깔끔해 보일 것 같아요! 🤔

Suggested change
const shop = res.data.item;
setForm({
name: shop.name,
category: shop.category,
address1: shop.address1,
address2: shop.address2,
originalHourlyPay: numberCommaFormatter(shop.originalHourlyPay),
description: shop.description,
});
if (shop.imageUrl) setImagePreview(shop.imageUrl);
const { name, category, address1, address2, originHourlyPay, description, imageUrl }
= res.data.item;
setForm({
name,
category,
address1,
address2,
originalHourlyPay: numberCommaFormatter(originalHourlyPay),
description,
});
if (imageUrl) setImagePreview(imageUrl);

Comment on lines +60 to +61
category: "" as ShopCategory,
address1: "" as SeoulDistrict,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오..! 여기에 as 타입 단언이 들어간 이유가 있나요?!
궁금합니다! 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

초기값으로 빈 문자열을 두면 아래와 같은 오류가 발생하더라구요!

Type '""' is not assignable to type '"한식" | "중식" | "일식" | "양식" | "분식" | "카페" | "편의점" | "기타"'.

ShopCategory"한식" | "중식" | "일식" | ...와 같은 리터럴 유니언 타입이라서 "한식"은 괜찮아도 ""는 허용하지 않는 것 같아요. 위와 같이 as 타입 단언을 사용해 지금은 빈 문자열이지만, 나중에 반드시 올바른 ShopCategory 또는 SeoulDistrict 값으로 바뀔 거라고 말해주는 방식을 사용해보았습니다!

Comment on lines 98 to 104
const reader = new FileReader();
reader.onload = () => {
if (typeof reader.result === "string") {
setImagePreview(reader.result);
}
};
reader.readAsDataURL(file);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL.createObjectURL API를 활용한 코드가
위->아래 흐름으로 더 보기 쉬운 것 같아요! 🤔

Suggested change
const reader = new FileReader();
reader.onload = () => {
if (typeof reader.result === "string") {
setImagePreview(reader.result);
}
};
reader.readAsDataURL(file);
// 이미 메모리에 blobURL이 존재한다면 해제하기
if(imagePreview) {
URL.revokeObjectURL(imagePreview);
}
// blobURL 생성하기
const blobUrl = URL.createObjectURL(file);
setImagePreview(blobUrl);

Comment on lines 131 to 155
try {
setIsSubmitting(true);

let imageUrl = imagePreview || "";
if (imageFile) {
const presignedURL = await postImage(imageFile.name);
await putImage(presignedURL, imageFile);
imageUrl = getPublicURL(presignedURL);
}

const payload = {
name: form.name.trim(),
category: form.category,
address1: form.address1,
address2: form.address2.trim(),
originalHourlyPay: hourlyPay,
description: form.description.trim(),
imageUrl,
};

await putShop(shopId, payload);
navigate("/shop");
} finally {
setIsSubmitting(false);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하나의 의견입니다! 😅

기존에 작성해주신 코드는
비동기 요청과 관련된 변수들을 가까이 두시려는 의도로 보이는데요 🤔

에러 발생가능성이 높은 비동기 요청과
에러 발생 가능성이 없는 변수를 번갈아봐야 해서
조금 읽기가 어려울 수 있을 것 같아요.

Suggested change
try {
setIsSubmitting(true);
let imageUrl = imagePreview || "";
if (imageFile) {
const presignedURL = await postImage(imageFile.name);
await putImage(presignedURL, imageFile);
imageUrl = getPublicURL(presignedURL);
}
const payload = {
name: form.name.trim(),
category: form.category,
address1: form.address1,
address2: form.address2.trim(),
originalHourlyPay: hourlyPay,
description: form.description.trim(),
imageUrl,
};
await putShop(shopId, payload);
navigate("/shop");
} finally {
setIsSubmitting(false);
}
setIsSubmitting(true);
let imageUrl = imagePreview || "";
const payload = {
name: form.name.trim(),
category: form.category,
address1: form.address1,
address2: form.address2.trim(),
originalHourlyPay: hourlyPay,
description: form.description.trim(),
imageUrl,
};
try {
if (imageFile) {
const presignedURL = await postImage(imageFile.name);
await putImage(presignedURL, imageFile);
imageUrl = getPublicURL(presignedURL);
}
await putShop(shopId, payload);
navigate("/shop");
} finally {
setIsSubmitting(false);
}

<h2 className="sm:text-[1.75rem] text-[1.25rem] font-bold">
가게 정보
</h2>
<button onClick={() => navigate("/shop")}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

라우트 상수를 활용하면 더 좋을 것 같아요 👍

import { ROUTES } from "./constants/router";
...  
export default function ShopRegisterPage() {
  ...
  return (
    ...
        <button onClick={() => navigate(ROUTES.SHOP.ROOT)}>
    ...
  );
}

Copy link
Collaborator

@jeonghwanJay jeonghwanJay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고 많으셨습니다 ~

setForm((prev) => ({ ...prev, [key]: value }));
};

const handleImageUpload = (e: ChangeEvent<HTMLInputElement>) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추후에 리팩토링을 하게 된다면 이미지 업로드 시 파일 크기나 형식 제한 정도 검증하는 유효성 검사를 고려해 볼 수 있을 것 같습니다.!

@almighty55555 almighty55555 merged commit 3f57864 into dev May 4, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature (기능 추가) 기능을 추가합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

가게 정보 편집 페이지 구현 (/shop/edit)

4 participants